package com.ai.service.cms.user.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.ai.common.analyze.CipherUtils;
import com.ai.common.enums.RedisTime;
import com.ai.common.exception.AlikAssert;
import com.ai.common.exception.BusinessException;
import com.ai.common.model.Pagination;
import com.ai.common.model.Result;
import com.ai.common.util.KeysEnum;
import com.ai.common.utils.CommonUtil;
import com.ai.common.utils.PatternUtils;
import com.ai.common.utils.cache.redis.shared.RedisUtils;
import com.ai.common.utils.lang.json.JsonUtils;
import com.ai.manager.edu.cms.user.BackendOperatorManager;
import com.ai.model.edu.cms.backoperator.BackendOperator;
import com.ai.model.edu.cms.backoperator.OperatorRole;
import com.ai.model.edu.cms.backoperator.Role;
import com.ai.model.edu.cms.backoperator.dto.BackendOperatorDTO;
import com.ai.model.edu.cms.backoperator.dto.OperatorRoleDTO;
import com.ai.model.edu.cms.backoperator.dto.RoleDTO;
import com.ai.model.edu.cms.backoperator.dto.RoleMenuDTO;
import com.ai.model.edu.cms.backoperator.vo.BackendOperatorVO;
import com.ai.model.edu.cms.backoperator.vo.MenuVO;
import com.ai.model.edu.cms.backoperator.vo.OperatorRoleVO;
import com.ai.model.edu.cms.backoperator.vo.RoleMenuVO;
import com.ai.model.edu.cms.backoperator.vo.RoleVO;
import com.ai.service.cms.user.BackendOperatorService;
import com.ai.service.cms.user.MenuService;
import com.ai.service.cms.user.OperatorRoleService;
import com.ai.service.cms.user.RoleMenuService;
import com.ai.service.cms.user.RoleService;
import com.fasterxml.jackson.databind.JavaType;

@Service("backendOperatorService")
public class BackendOperatorServiceImpl implements BackendOperatorService {
    
    private static final Logger logger = LoggerFactory.getLogger(BackendOperatorServiceImpl.class);
    // 冻结
    public static final int OPERATOR_STATUS_CLOSE = 0;

    // 开通
    public static final int OPERATOR_STATUS_OPEN = 1;

    // 是否超级用户
    public static final int IS_SUPER_USER = 1;

    @Resource
    private BackendOperatorManager backendOperatorManager;

    @Resource
    private OperatorRoleService operatorRoleService;

    @Resource
    private RoleMenuService roleMenuService;

    @Resource
    private RoleService roleService;
    @Resource
    private MenuService menuService;

    @Resource
    private RedisUtils redisUtils;

    /**
     * Description ： 根据用户名查找用户
     * 
     * nyj
     * 
     * @param userName
     * @return
     * @since
     *
     */
    public BackendOperatorVO findBackendOperatorByName(String userName) {
        // 参数校验
        if (StringUtils.isBlank(userName)) {
            BusinessException.throwMessage("用户名不能为空");
        }
        return backendOperatorManager.findBackendOperatorByName(userName);
    }

    /**
     * Description ： 根据dto(用户名+运营商id)查询用户信息<br>
     * 
     * yangwb
     * 
     * @param backendOperatorDTO
     * @return
     * @since
     *
     */
    public BackendOperatorVO findBackendOperatorByDTO(BackendOperatorDTO backendOperatorDTO) {
        AlikAssert.isNotNull(backendOperatorDTO, "参数对象不能为空！");
        AlikAssert.isNotBlank(backendOperatorDTO.getUserName(), "用户名不能为空！");
        return backendOperatorManager.findBackendOperatorByDTO(backendOperatorDTO);
    }

    /**
     * Description ： 登录验证
     * 
     * nyj
     * 
     * @param backendOperatorDTO
     * @return
     * @since
     *
     */
    @Transactional
    public BackendOperatorVO login(BackendOperatorDTO backendOperatorDTO) {
        // 参数校验
        AlikAssert.isNotNull(backendOperatorDTO, "参数错误");
        AlikAssert.isNotBlank(backendOperatorDTO.getPassword(), "密码不能为空");
        AlikAssert.isNotBlank(backendOperatorDTO.getUserName(), "用户名不能为空");
        AlikAssert.isNotBlank(backendOperatorDTO.getValidateCode(), "验证码不能为空");
        AlikAssert.isNotBlank(backendOperatorDTO.getSessionValidateCode(), "验证码失效，请刷新页面");
        // 检验验证码信息
        if (!backendOperatorDTO.getValidateCode().toUpperCase().equals(backendOperatorDTO.getSessionValidateCode())) {
            BusinessException.throwMessage("验证码错误");
        }
        BackendOperatorVO backendOperator = null;
        try {
            // 查找用户信息
            backendOperator = backendOperatorManager.findBackendOperatorByName(backendOperatorDTO.getUserName());
        } catch (Exception e) {
            logger.error("backendOperatorManager.findBackendOperatorByName is error ",e);
            BusinessException.throwMessage("系统异常，请稍后再试");
        }
        
        if (backendOperator == null) {
            BusinessException.throwMessage("用户不存在");
        }
        //检验用户状态
        if(backendOperator.getOperatorStatus() != null && backendOperator.getOperatorStatus().intValue() != 1){
        	BusinessException.throwMessage("用户未开通");
        }
        // 页面密码MD5加密
        String passwordMd5 = CipherUtils.MD5Encode(backendOperatorDTO.getPassword());
        if (!backendOperator.getPassword().equals(passwordMd5)) {
            BusinessException.throwMessage("密码错误");
        }
        // 登录成功后更新用户信息
        backendOperatorDTO.setUpdateBy(backendOperator.getId());
        backendOperatorManager.updateBackendOperatorAfterLogin(backendOperatorDTO);
        return backendOperator;

    }

    /**
     * Description ： 根据DTO查询用户分页信息<br>
     * 
     * yangwb
     * 
     * @param backendOperatorDTO
     * @return
     * @since
     * 
     */
    public Pagination<BackendOperatorVO> findBackendVOSPgByDTO(BackendOperatorDTO backendOperatorDTO) {
        if (backendOperatorDTO == null) {
            return new Pagination<BackendOperatorVO>();
        }
        return backendOperatorManager.findBackendVOSPgByDTO(backendOperatorDTO);
    }

    /**
     * Description ： 新增or编辑用户信息<br>
     * 
     * yangwb
     * 
     * @param backendOperator
     * @return
     * @since
     *
     */
    @Transactional
    public Result addOrUpdateBackendOperator(BackendOperator backendOperator) {
    	Result result = new Result();
        // 校验用户输入信息
    	int flag = 0;
        this.validateUserInfo(backendOperator);
        if (backendOperator.getId() == null) {
            // 密码MD5加密
            backendOperator.setPassword(CipherUtils.MD5Encode(backendOperator.getPassword()));
            backendOperator.setRecentlyPassword(backendOperator.getPassword());
            // 新增
            flag = backendOperatorManager.addBackendOperator(backendOperator);
            if (flag <= 0) {
                BusinessException.throwMessageWithCode("-12", "新增用户信息失败");
            }
        } else {
            // 密码不为空 表示 有更新 做加密
            if (!StringUtils.isBlank(backendOperator.getPassword())) {
                // 密码MD5加密
                backendOperator.setPassword(CipherUtils.MD5Encode(backendOperator.getPassword()));
                // 密码不能与前三次密码重复
                // 获取之前存在的密码
                String recentlyPassword = backendOperator.getRecentlyPassword();
                // 加密后的密码
                String pwd = backendOperator.getPassword();
                if (!StringUtils.isBlank(recentlyPassword)) {
                    String[] rePwd = recentlyPassword.split(",");
                    for (int i = 0; i < rePwd.length; i++) {
                        // 判断当前密码是否与最近密码相同
                        if (rePwd[i].equals(pwd)) {
                            BusinessException.throwMessageWithCode("-2", "当前密码与前三次密码相同，请更换密码后重试！");
                        }
                    }
                    StringBuffer sb = new StringBuffer();
                    for (int i = 0; i < rePwd.length; i++) {
                        if (rePwd.length >= 3) {
                            if (i == 0) {
                                continue;
                            }
                        }
                        if (StringUtils.isBlank(sb.toString())) {
                            sb.append(rePwd[i]);
                        } else {
                            sb.append(",").append(rePwd[i]);
                        }
                    }
                    // 判断是否已经存在 旧密码
                    if (StringUtils.isBlank(sb.toString())) {
                        sb.append(pwd);
                    } else {
                        sb.append(",").append(pwd);
                    }
                    // 设置密码
                    backendOperator.setRecentlyPassword(sb.toString());
                } else {
                    backendOperator.setRecentlyPassword(pwd);
                }
            }
            // 编辑
            flag = backendOperatorManager.updateBackendOperator(backendOperator);
            if (flag <= 0) {
                BusinessException.throwMessageWithCode("-3", "更新用户失败！");
            }
        }
        return result;
    }

    /**
     * Description ： 校验用户输入信息<br>
     * 
     * yangwb
     * 
     * @param backendOperator
     * @since
     * 
     */
    private void validateUserInfo(BackendOperator backendOperator) {
        // 参数校验
        AlikAssert.isNotNull(backendOperator, "参数对象不能为空！");
        AlikAssert.isNotBlank(backendOperator.getUserName(), "用户登录账号不能为空！");
        AlikAssert.isNotBlank(backendOperator.getRealName(), "用户姓名不能为空！");
        AlikAssert.isNotBlank(backendOperator.getPassword(), "用户登录密码不能为空！");
        AlikAssert.isNotBlank(backendOperator.getConfirmPassword(), "用户确认密码不能为空！");
        AlikAssert.isNotNull(backendOperator.getOperatorStatus(), "用户账号状态不能为空");
        String userName = backendOperator.getUserName().trim();
        // 登录账号必须唯一校验 中文、数字、字母组合 （不包含特殊字符）长度不超过30个字符
        if (userName.length() > 30) {
            BusinessException.throwMessageWithCode("-4", "登录账号长度不能超过30个字符！");
        }
        // 判断用户名是否是由中文、数字、字母组合
        if (!PatternUtils.matchText(userName)) {
            BusinessException.throwMessageWithCode("-5", "登录账号只能由中文、数字、字母组合！");
        }
        // 校验唯一性 根据用户名查询用户
        BackendOperatorDTO backendOperatorDTO = new BackendOperatorDTO();
        backendOperatorDTO.setId(backendOperator.getId());
        backendOperatorDTO.setUserName(backendOperator.getUserName());
        // 新增or更新 做重名校验 根据用户名 or Id查询
        List<BackendOperatorVO> operatorVOs = backendOperatorManager.findBackendOperatorVOs(backendOperatorDTO);
        // 判断是否重名 若已经存在 抛异常
        if(!CollectionUtils.isEmpty(operatorVOs)){
        	BusinessException.throwMessageWithCode("-6", "已经存在用户名为【" + userName + "】的用户，请更换用户名后重试！");
        }

        String password = backendOperator.getPassword().trim();
        String confirmPassword = backendOperator.getConfirmPassword().trim();
        // 判断确认密码是否与登录密码一致
        if (!confirmPassword.equals(password)) {
            BusinessException.throwMessageWithCode("-7", "确认密码必须与原密码一致！");
        }
        // 更新时 先取出数据库中的用户对象判断密码是否有过更新
        if (backendOperator.getId() == null) {
            // 密码 6位或以上长度、不能与前3次密码重复 、有效期90天 、 不包含用户的姓名或账户名
            // 包含 四类中的三类 ；1、大写英文字母 2、小写英文字母 3、10个基本数字、4、非字母字符
            this.validatePwd(backendOperator, userName, password);
        } else {
            // TODO
            // 根据id 查询用户对象
            BackendOperatorVO backendOperatorVO = backendOperatorManager.findBackendOperatorVOById(backendOperator.getId());
            if (backendOperatorVO.getPassword().equals(password)) {
                // 密码未改变 此时 改变用户名和姓名 密码可能存在问题
                backendOperator.setPassword("");
            } else {
                // 校验密码格式
                this.validatePwd(backendOperator, userName, password);
                backendOperator.setRecentlyPassword(backendOperatorVO.getRecentlyPassword());
            }
        }
    }

    /**
     * Description ： 校验密码<br>
     * 
     * yangwb
     * 
     * @param backendOperator
     * @param userName
     * @param password
     * @since
     * 
     */
    private void validatePwd(BackendOperator backendOperator, String userName, String password) {
        if (password.length() < 6) {
            BusinessException.throwMessageWithCode("-8", "密码长度必须6位以上！");
        }
        // 判断用户密码是否包含用户名和真实姓名
//        if (password.indexOf(PinYinUtils.getPingYin(userName)) > -1) {
//            BusinessException.throwMessageWithCode("-8", "密码长度必须6位以上！");
//        }
//        if (password.indexOf(PinYinUtils.getPingYin(backendOperator.getRealName())) > -1) {
//            BusinessException.throwMessageWithCode("-8", "密码长度必须6位以上！");
//        }
        // 校验密码是否由三种组成 大写字母/小写字母/数字/特殊字符
        if (!PatternUtils.matchPassword(password)) {
            BusinessException.throwMessageWithCode("-9", "密码至少包含大写字母、小写字母、数字、特殊字符中的三种！");
        }
    }

    /**
     * Description ： 根据dto更新用户（开启冻结状态）状态<br>
     * 
     * yangwb
     * 
     * @param backendOperatorDTO
     * @return
     * @since
     * 
     */
    @Transactional
    public int updateBackendUserStatusByDTO(BackendOperatorDTO backendOperatorDTO) {
        AlikAssert.isNotNull(backendOperatorDTO, "参数对象不能为空！");
        AlikAssert.isNotNull(backendOperatorDTO.getId(), "用户id不能为空！");
        AlikAssert.isNotNull(backendOperatorDTO.getOperatorStatus(), "更新状态不能为空！");
        AlikAssert.isNotNull(backendOperatorDTO.getUpdateBy(), "更新操作人不能为空！");
        // 需要冻结 设置前置状态
        if (backendOperatorDTO.getOperatorStatus().equals(OPERATOR_STATUS_CLOSE)) {
            backendOperatorDTO.setOldStatus(OPERATOR_STATUS_OPEN);
        } else if (backendOperatorDTO.getOperatorStatus().equals(OPERATOR_STATUS_OPEN)) {
            // 开通
            backendOperatorDTO.setOldStatus(OPERATOR_STATUS_CLOSE);
        } else {
            AlikAssert.isFalse(true, "更新状态入参异常！");
            BusinessException.throwMessageWithCode("-12", "更新状态入参异常！");
        }
        int result = backendOperatorManager.updateBackendUserStatusByDTO(backendOperatorDTO);
        if (result <= 0) {
            BusinessException.throwMessageWithCode("-3", "更新用户状态失败，请刷新后重试！");
        }
        return result;
    }

    /**
     * Description ： 根据dto删除用户<br>
     * 
     * yangwb
     * 
     * @param backendOperatorDTO
     * @return
     * @since
     * 
     */
    @Transactional
    public int deleteBackOperatorByDTO(BackendOperatorDTO backendOperatorDTO) {
        AlikAssert.isNotNull(backendOperatorDTO, "参数对象不能为空！");
        AlikAssert.isNotNull(backendOperatorDTO.getId(), "用户id不能为空！");
        AlikAssert.isNotNull(backendOperatorDTO.getUpdateBy(), "更新操作人不能为空！");
        int result = backendOperatorManager.deleteBackOperatorByDTO(backendOperatorDTO);
        if (result <= 0) {
            BusinessException.throwMessageWithCode("-12", "删除用户失败，请刷新后重试！");
        }
        OperatorRoleDTO operatorRoleDTO = new OperatorRoleDTO();
        operatorRoleDTO.setBackOperatorId(backendOperatorDTO.getId());
        List<OperatorRoleVO> list = operatorRoleService.findUserRoleVOsByDTO(operatorRoleDTO);
        // list 不为空
        if (!CollectionUtils.isEmpty(list)) {
            // 先删除、后新增
            result = operatorRoleService.deleteUserRoleByBackOperatorId(backendOperatorDTO.getId());
            if (result == 0 || result != list.size()) {
                BusinessException.throwMessageWithCode("-13", "删除用户角色关系失败,请刷新页面后重试！");
            }
        }
        return result;
    }

    /**
     * Description ： 批量新增用户角色关系<br>
     * 
     * yangwb
     * 
     * @param backendOperatorDTO
     * @since
     * 
     */
    @Transactional
    public void addBackOperatorRoleByDTO(BackendOperatorDTO backendOperatorDTO) {
        AlikAssert.isNotNull(backendOperatorDTO, "参数对象不能为空！");
        AlikAssert.isNotNull(backendOperatorDTO.getId(), "用户id不能为空！");
        AlikAssert.isNotNull(backendOperatorDTO.getUpdateBy(), "更新操作人不能为空！");
        AlikAssert.isNotEmpty(backendOperatorDTO.getOperatorRoleDTOs(), "用户角色关系信息不能为空");

        OperatorRoleDTO operatorRoleDTO = new OperatorRoleDTO();
        operatorRoleDTO.setBackOperatorId(backendOperatorDTO.getId());
        // 根据backendOperatorId查询用户角色关系
        List<OperatorRoleVO> userRoleVOs = operatorRoleService.findUserRoleVOsByDTO(operatorRoleDTO);

        // 页面入参 新的用户角色关系
        List<OperatorRoleDTO> operatorRoleDTOs = backendOperatorDTO.getOperatorRoleDTOs();
        // 需要添加
        List<OperatorRole> operatorRoles = new ArrayList<OperatorRole>();
        for (OperatorRoleDTO operatorRoleDTONew : operatorRoleDTOs) {
            OperatorRole operatorRole = new OperatorRole();
            operatorRole.setRoleId(operatorRoleDTONew.getRoleId());
            operatorRole.setBackOperatorId(operatorRoleDTONew.getBackOperatorId());
            operatorRole.setCreateBy(backendOperatorDTO.getUpdateBy());
            operatorRoles.add(operatorRole);
        }
        // 之前不存在用户角色关系 直接做新增
        if (CollectionUtils.isEmpty(userRoleVOs)) {
            // 做新增操作
            operatorRoleService.addUserRoleBatch(operatorRoles);
        } else {
            // 先删除、后新增
            int result = operatorRoleService.deleteUserRoleByBackOperatorId(backendOperatorDTO.getId());
            if (result == 0 || result != userRoleVOs.size()) {
                AlikAssert.isFalse(true, "删除用户角色关系失败,请刷新页面后重试！");
            }
            // 做新增操作
            operatorRoleService.addUserRoleBatch(operatorRoles);
        }
    }

    /**
     * Description ： 批量新增和删除用户角色关系<br>
     * 
     * yangwb
     * 
     * @param backendOperatorDTO
     * @since
     * 
     */
    @Transactional
    public void addAndDelBackOperatorRole(Long operatorId, Long backOperatorId, String addRoleIds, String delRoleIds) {
        String[] addIds = null;
        String[] delIds = null;
        if (!StringUtils.isEmpty(addRoleIds)) {
            addIds = addRoleIds.split(",");
        }
        if (!StringUtils.isEmpty(delRoleIds)) {
            delIds = delRoleIds.split(",");
        }
        // 需要添加
        if (null != addIds) {
            // 添加ids
            List<Long> addRoleIdList = new ArrayList<Long>();
            for (int i = 0; i < addIds.length; i++) {
                addRoleIdList.add(Long.valueOf(addIds[i]));
            }
            if (!CollectionUtils.isEmpty(addRoleIdList)) {
                OperatorRoleDTO userRoleDTO = new OperatorRoleDTO();
                userRoleDTO.setRoleIds(addRoleIdList);
                userRoleDTO.setBackOperatorId(backOperatorId);
                Map<Long, OperatorRoleVO> addOperatorRoleMap = operatorRoleService.findOperatorRoleMap(userRoleDTO);
                for (Long roleId : addRoleIdList) {
                    if (CollectionUtils.isEmpty(addOperatorRoleMap) || (!CollectionUtils.isEmpty(addOperatorRoleMap) && addOperatorRoleMap.get(roleId) == null)) {
                        // 当前角色用户关系不存在 新增
                        OperatorRole operatorRole = new OperatorRole();
                        operatorRole.setRoleId(roleId);
                        operatorRole.setBackOperatorId(backOperatorId);
                        operatorRole.setCreateBy(operatorId);
                        operatorRoleService.insert(operatorRole);
                    }
                }
            }
        }
        // 删除
        if (null != delIds) {
            // 添加ids
            List<Long> delRoleIdList = new ArrayList<Long>();
            for (int i = 0; i < delIds.length; i++) {
                delRoleIdList.add(Long.valueOf(delIds[i]));
            }
            if (!CollectionUtils.isEmpty(delRoleIdList)) {
                operatorRoleService.removeOperatorRoleByRoleIdsAndOperatorId(backOperatorId, delRoleIdList);
            }

        }
    }

    /**
     * Description ： 根据用户id查询该用户下的权限信息 <br>
     * 
     * yangwb
     * 
     * @param id
     * @return map key:functionCode value:MenuVO
     * @since
     * 
     */
    @SuppressWarnings("unchecked")
	public Map<String, MenuVO> findMenuVOSById(Long id) {
        // 获取权限key
        String key = KeysEnum.BACKEND_MENU_FUNCTION.getKey() + "_" + id;
        Map<String, MenuVO> map = new HashMap<String, MenuVO>();
        // 从缓存中取数据
        String menuJson = redisUtils.get(key);
        if (!StringUtils.isBlank(menuJson)) {
        	Map<String, MenuVO> menuMap = JsonUtils.fromJson(menuJson, Map.class);
        	map.putAll(menuMap);
            return map;
        } else {
            OperatorRoleDTO operatorRoleDTO = new OperatorRoleDTO();
            operatorRoleDTO.setBackOperatorId(id);
            // 根据id 查询用户角色关系list
            List<OperatorRoleVO> userRoles = operatorRoleService.findUserRoleVOsByDTO(operatorRoleDTO);
            // 判断是否存在用户角色关系
            if (CollectionUtils.isEmpty(userRoles)) {
                return map;
            }
            // 获取所有的角色ids
            List<Long> roleIds = CommonUtil.getValueList(userRoles, "roleId");
            // 根据角色ids查询角色信息 过滤掉冻结的角色
            List<RoleVO> roleVos = roleService.findRoleVOsByIds(roleIds);
            // 判断角色是否存在
            if (CollectionUtils.isEmpty(roleVos)) {
                return map;
            }
            // 获取可用的角色ids
            List<Long> roleIdsCanUser = CommonUtil.getValueList(roleVos, "id");
            // 获取角色对应的菜单关系
            List<RoleMenuVO> roleMenus = roleMenuService.findRoleMunuVOsByRoleIds(roleIdsCanUser);
            if (CollectionUtils.isEmpty(roleMenus)) {
                return map;
            }
            // 获取所有的菜单ids
            List<Long> menuIds = CommonUtil.getValueList(roleMenus, "menuId");
            // 获取所有菜单
            List<MenuVO> menuVOS = menuService.findMenuVOSByIds(menuIds);
            if (CollectionUtils.isEmpty(menuVOS)) {
                return map;
            }
            // 循环放入map中
            for (MenuVO menuVO : menuVOS) {
                if (!StringUtils.isBlank(menuVO.getMenuCode())) {
                    if (map.get(menuVO.getMenuCode().trim()) == null) {
                        map.put(menuVO.getMenuCode().trim(), menuVO);
                    }
                }
            }
            // 放置入缓存中
            redisUtils.setex(key, RedisTime.HALF_AN_HOUR, JsonUtils.toJson(map));
        }
        return map;
    }

    /**
     * Description ： 根据id 查询该用户下的所有菜单 / 分超级用户跟普通用户<br>
     * 
     * yangwb
     * 
     * @param id
     * @return
     * @since
     *
     */
    public List<MenuVO> findMenuVOS(Long id) {
        // 根据id 查询backOperator 用户对象
        BackendOperatorVO backendOperatorVO = backendOperatorManager.findBackendOperatorVOById(id);
        AlikAssert.isNotNull(backendOperatorVO, "当前用户不存在！");
        // 左边菜单
        List<MenuVO> menuVOs = new ArrayList<MenuVO>();
        if (backendOperatorVO.getIsSuperUser().equals(IS_SUPER_USER)) {
            String key = KeysEnum.BACKEND_SUPER_FUNCTION.getKey();
            // 超级用户 取出所有菜单
            String menusJson = redisUtils.get(key);
            if (!StringUtils.isBlank(menusJson)) {
                JavaType menuJavaType = JsonUtils.constructParametricType(ArrayList.class, MenuVO.class);
                menuVOs = JsonUtils.fromJson(menusJson, menuJavaType);
                return menuVOs;
            } else {
                // 缓存中没有 查出所有的可用菜单
                menuVOs = menuService.findAllActiveMenuVOs();
                // 放置入缓存中
                redisUtils.setex(key, RedisTime.HALF_AN_HOUR, JsonUtils.toJson(menuVOs));
                return menuVOs;
            }
        } else {
            String key = KeysEnum.BACKEND_NORMAL_FUNCTION.getKey() + "_" + id;
            // 普通用户 取出用户下的菜单
            String menusJson = redisUtils.get(key);
            if (!StringUtils.isBlank(menusJson)) {
                JavaType menuJavaType = JsonUtils.constructParametricType(ArrayList.class, MenuVO.class);
                menuVOs = JsonUtils.fromJson(menusJson, menuJavaType);
                return menuVOs;
            } else {
                OperatorRoleDTO operatorRoleDTO = new OperatorRoleDTO();
                operatorRoleDTO.setBackOperatorId(id);
                // 根据id 查询用户角色关系list
                List<OperatorRoleVO> userRoles = operatorRoleService.findUserRoleVOsByDTO(operatorRoleDTO);
                // 判断是否存在用户角色关系
                if (CollectionUtils.isEmpty(userRoles)) {
                    return menuVOs;
                }
                // 获取所有的角色ids
                List<Long> roleIds = CommonUtil.getValueList(userRoles, "roleId");
                // 根据角色ids查询角色信息 过滤掉冻结的角色
                List<RoleVO> roleVos = roleService.findRoleVOsByIds(roleIds);
                // 判断角色是否存在
                if (CollectionUtils.isEmpty(roleVos)) {
                    return menuVOs;
                }
                // 获取可用的角色ids
                List<Long> roleIdsCanUser = CommonUtil.getValueList(roleVos, "id");
                // 获取角色对应的菜单关系
                List<RoleMenuVO> roleMenus = roleMenuService.findRoleMunuVOsByRoleIds(roleIdsCanUser);
                if (CollectionUtils.isEmpty(roleMenus)) {
                    return menuVOs;
                }
                // 获取所有的菜单ids
                List<Long> menuIds = CommonUtil.getValueList(roleMenus, "menuId");
                Set<Long> set = new HashSet<Long>();
                List<Long> menuIdsNew = new ArrayList<Long>();
                for (Long menuId : menuIds) {
                    if (set.add(menuId)) {
                        menuIdsNew.add(menuId);
                    }
                }
                // 获取所有菜单
                menuVOs = menuService.findMenuVOSByIds(menuIdsNew);
                if (CollectionUtils.isEmpty(menuVOs)) {
                    return menuVOs;
                }
                // 放置入缓存中
                redisUtils.setex(key, RedisTime.HALF_AN_HOUR, JsonUtils.toJson(menuVOs).toString());
                return menuVOs;
            }
        }
    }

    /**
     * Description ： 用户自己修改信息<br>
     * 
     * zhangdh
     * 
     * @param backendOperatorDTO
     * @return
     * @since
     *
     */
    @Transactional
    @Override
    public int updateMyBackendOperator(BackendOperatorDTO backendOperatorDTO, BackendOperatorVO operatorVO) {
        AlikAssert.isNotNull(backendOperatorDTO, "错误，原因：入参为空！");
        AlikAssert.isNotNull(backendOperatorDTO.getId(), "错误，原因：用户id为空！");
        // 校验用户输入信息
        int result = 0;
        // 密码不为空 表示 有更新 做加密
        if (!StringUtils.isBlank(backendOperatorDTO.getPassword())) {
            // 密码MD5加密
            String oldPassword = CipherUtils.MD5Encode(backendOperatorDTO.getPassword());
            // 检查用户输入密码是否与数据库一致
            if (!oldPassword.equals(operatorVO.getPassword())) {
                BusinessException.throwMessageWithCode("-12", "旧密码错误！");
            }
            // 获取新密码与确认密码
            String newPassword = StringUtils.trim(backendOperatorDTO.getNewPassword());
            String confirmNewPassword = StringUtils.trim(backendOperatorDTO.getConfirmNewPassword());
            // 检查密码是否一致
            if (!newPassword.equals(confirmNewPassword)) {
                BusinessException.throwMessageWithCode("-2", "新密码与确认密码不一致！");
            }
            // 检查新密码是否符合规则
            this.validatePwd(operatorVO, operatorVO.getUserName(), newPassword);
            // 设置新密码为加密后的密码
            backendOperatorDTO.setNewPassword(CipherUtils.MD5Encode(newPassword));
            // 密码不能与前三次密码重复
            // 获取之前存在的密码
            String recentlyPassword = operatorVO.getRecentlyPassword();
            // 加密后的密码
            String pwd = backendOperatorDTO.getNewPassword();
            if (!StringUtils.isBlank(recentlyPassword)) {
                String[] rePwd = recentlyPassword.split(",");
                for (int i = 0; i < rePwd.length; i++) {
                    // 判断当前密码是否与最近密码相同
                    if (rePwd[i].equals(pwd)) {
                        BusinessException.throwMessageWithCode("-3", "当前密码与前三次密码相同，请更换密码后重试！");
                    }
                }
                StringBuffer sb = new StringBuffer();
                for (int i = 0; i < rePwd.length; i++) {
                    if (rePwd.length >= 3) {
                        if (i == 0) {
                            continue;
                        }
                    }
                    if (StringUtils.isBlank(sb.toString())) {
                        sb.append(rePwd[i]);
                    } else {
                        sb.append(",").append(rePwd[i]);
                    }
                }
                // 判断是否已经存在 旧密码
                if (StringUtils.isBlank(sb.toString())) {
                    sb.append(pwd);
                } else {
                    sb.append(",").append(pwd);
                }
                // 设置密码
                backendOperatorDTO.setRecentlyPassword(sb.toString());
            } else {
                backendOperatorDTO.setRecentlyPassword(pwd);
            }
            // 修改密码，封装入参
            BackendOperator backendOperator = new BackendOperator();
            backendOperator.setId(backendOperatorDTO.getId());
            backendOperator.setUpdateBy(backendOperatorDTO.getUpdateBy());
            backendOperator.setPassword(backendOperatorDTO.getNewPassword());
            backendOperator.setRecentlyPassword(backendOperatorDTO.getRecentlyPassword());
            // 更新密码
            result = backendOperatorManager.updateBackendOperator(backendOperator);
            if (result <= 0) {
                BusinessException.throwMessageWithCode("-4", "修改密码失败！");
            }
        } else {
            // 用户自己修改个人资料，封装入参
            BackendOperator backendOperator = new BackendOperator();
            backendOperator.setId(backendOperatorDTO.getId());
            backendOperator.setUpdateBy(backendOperatorDTO.getUpdateBy());
            backendOperator.setStaffNo(backendOperatorDTO.getStaffNo());
            backendOperator.setMobile(backendOperatorDTO.getMobile());
            // 编辑更新
            result = backendOperatorManager.updateBackendOperator(backendOperator);
            if (result <= 0) {
                BusinessException.throwMessageWithCode("-5", "更新用户资料失败！");
            }
        }
        return result;
    }

    /**
     * Description ： 根据主键id查询用户对象<br>
     * 
     * yangwb
     * 
     * @param id
     * @return
     * @since
     * 
     */
    public BackendOperatorVO findBackendOperatorVOById(Long id) {
        return backendOperatorManager.findBackendOperatorVOById(id);
    }

    /**
     * 
     * Method Name : updateRoleMenu<br>
     * 
     * Description : 更新觉得roleId的菜单权限<br>
     * 
     * @param roleMenuDTO
     * @param roleId
     * @param backOperatorId
     * @return
     * @since
     *
     */
    @Transactional
    public String updateRoleMenu(RoleMenuDTO roleMenuDTO, Long operatorId) {
        return roleMenuService.updateRoleMenu(roleMenuDTO, operatorId);
    }

    /**
     * Description ： 新增角色信息
     * 
     * nyj
     * 
     * @since
     *
     */
    @Transactional
    public void addRoleInfo(Role role) {
        roleService.addRoleInfo(role);
    }

    /**
     * Description ：启用角色
     * 
     * nyj
     * 
     * @param roleDTO
     * @return
     * @since
     *
     */
    @Transactional
    public int enableRole(RoleDTO roleDTO) {
        return roleService.enableRole(roleDTO);
    }

    /**
     * Description ：冻结角色
     * 
     * nyj
     * 
     * @param roleDTO
     * @return
     * @since
     *
     */
    @Transactional
    public int unableRole(RoleDTO roleDTO) {
        return roleService.unableRole(roleDTO);
    }

    /**
     * Description ： 批量新增用户
     * 
     * nyj
     * 
     * @param role
     * @since
     *
     */
    @Transactional
    public void addRole2User(OperatorRoleDTO operatorRoleDTO) {
        operatorRoleService.addRole2User(operatorRoleDTO);
    }

    /**
     * Description ： 根据ID删除角色
     * 
     * nyj
     * 
     * @param roleDTO
     * @return
     * @since
     *
     */
    @Transactional
    public int deleteRoleById(RoleDTO roleDTO) {
        return roleService.deleteRoleById(roleDTO);
    }

    /**
     * Description  ： 根据创建人姓名模糊查询数据<br>
     * 
     * wumc
     * @param term
     * @return
     * @since
     *
     */
    @Override
    public List<BackendOperatorVO> findOperatorListByName(String term) {
        return backendOperatorManager.findOperatorListByName(term);
    }

    public static void main(String[] args) {
        // Map<String, MenuVO> map = new HashMap<String, MenuVO>();
        // MenuVO menuVO = new MenuVO();
        // menuVO.setMenuCode("23423542");
        // map.put("fsdfsdf", menuVO);
        // String json = JSONObject.toJSON(map).toString();
        //
        // JSONObject parseObject = JSONObject.parseObject(json);
        //
        // Map<String, MenuVO> map3 = new HashMap<String, MenuVO>();
        // parseObject.entrySet();
        // for (Entry<String, Object> map2 : parseObject.entrySet()) {
        // map2.getKey();
        // parseObject.getObject(map2.getKey(), MenuVO.class);
        // map2.getValue();
        // map3.put(map2.getKey(), parseObject.getObject(map2.getKey(),
        // MenuVO.class));
        // }
        //
        // // MenuVO menuVO2 = parseObject.getObject("fsdfsdf", MenuVO.class);
        //
        // System.out.println(map3);

        List<Long> ids = new ArrayList<Long>();
        ids.add(1l);
        ids.add(2l);

        // JSONObject.parseObject(JSONObject.toJSON(ids).toString());
        JavaType menuJavaType = JsonUtils.constructParametricType(ArrayList.class, Long.class);
        List<Long> newIds = JsonUtils.fromJson(JsonUtils.toJson(ids), menuJavaType);
        
        for (Long id : newIds) {
            System.out.println(id);
        }
        // System.out.println(JSONObject.parseArray(JSONObject.toJSON(ids).toString()));

    }

}
